﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Management;
using NetworkAssetManager.Entity;
using System.Collections;
using log4net; 
namespace NetworkAssetManager.WMI
{
    public class OS
    {
        private static readonly ILog _logger = LogManager.GetLogger(typeof(OS));

        private static string DecodeProductKey(Byte[] digitalProductId)
        {
            // Offset of first byte of encoded product key in 
            //  'DigitalProductIdxxx" REG_BINARY value. Offset = 34H.
            const int keyStartIndex = 52;
            // Offset of last byte of encoded product key in 
            //  'DigitalProductIdxxx" REG_BINARY value. Offset = 43H.
            const int keyEndIndex = keyStartIndex + 15;
            // Possible alpha-numeric characters in product key.
            char[] digits = new char[]
                  {
                    'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R', 
                    'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9',
                  };
            // Length of decoded product key
            const int decodeLength = 29;
            // Length of decoded product key in byte-form.
            // Each byte represents 2 chars.
            const int decodeStringLength = 15;
            // Array of containing the decoded product key.
            char[] decodedChars = new char[decodeLength];
            // Extract byte 52 to 67 inclusive.
            ArrayList hexPid = new ArrayList();
            for (int i = keyStartIndex; i <= keyEndIndex; i++)
            {
                hexPid.Add(digitalProductId[i]);
            }
            for (int i = decodeLength - 1; i >= 0; i--)
            {
                // Every sixth char is a separator.
                if ((i + 1) % 6 == 0)
                {
                    decodedChars[i] = '-';
                }
                else
                {
                    // Do the actual decoding.
                    int digitMapIndex = 0;
                    for (int j = decodeStringLength - 1; j >= 0; j--)
                    {
                        int byteValue = (digitMapIndex << 8) | (byte)hexPid[j];
                        hexPid[j] = (byte)(byteValue / 24);
                        digitMapIndex = byteValue % 24;
                        decodedChars[i] = digits[digitMapIndex];
                    }
                }
            }
            return new string(decodedChars);
        }

        private static EntOS FillDetails (ManagementBaseObject obj)
        {
            EntOS objEntOs = new EntOS(); 

            try
            {
                objEntOs.InstallDate = WMIUtil.ToDateTime((string)obj["InstallDate"]);
            }
            catch (Exception)
            {
                objEntOs.InstallDate = DateTime.MinValue; 
            }

            try
            {
                objEntOs.LastBootupTime = WMIUtil.ToDateTime((string)obj["LastBootUpTime"]);
            }
            catch (Exception)
            {
                objEntOs.LastBootupTime = DateTime.MinValue;
            }


            try
            {
                objEntOs.Name = WMIUtil.ToString(obj["Caption"]);
            }
            catch (Exception)
            {
                objEntOs.Name = "";
            }

            try
            {
                objEntOs.BuildNo = WMIUtil.ToString(obj["BuildNumber"]);
            }
            catch (Exception)
            {
                objEntOs.BuildNo = "";
            }

            try
            {
                objEntOs.Version = WMIUtil.ToString(obj["Version"]);
            }
            catch (Exception)
            {
                objEntOs.Version = "";
            }

            try
            {
                objEntOs.ServicePack = WMIUtil.ToString(obj["CSDVersion"]);
            }
            catch (Exception)
            {
                objEntOs.ServicePack = "";
            }

            try
            {
                objEntOs.WindowsID = WMIUtil.ToString(obj["SerialNumber"]);
            }
            catch (Exception)
            {
                objEntOs.WindowsID = "";  
            }

            objEntOs.SerialKey = "Yet to be implemented";

            return objEntOs; 
        }
        public static List<EntOS> GetOSDetails(ManagementScope scope) 
        {
            _logger.Info("Collecting OS details for machine " + scope.Path.Server);

            ObjectQuery query = null;
            ManagementObjectSearcher searcher = null;
            ManagementObjectCollection objects = null;
            List<EntOS> lstOS = new List<EntOS>();

            try
            {
                query = new ObjectQuery("Select * from Win32_OperatingSystem");
                searcher = new ManagementObjectSearcher(scope, query);
                objects = searcher.Get();
                lstOS.Capacity = objects.Count;
                foreach (ManagementBaseObject obj in objects)
                {
                    lstOS.Add(FillDetails(obj));
                    obj.Dispose();
                }
            }
            catch (System.Exception e)
            {
                _logger.Error("Exception in OS collection " + e.Message);
            }
            finally
            {
                searcher.Dispose();
            }
            return lstOS;
        }
    }
}
